package com.zang.blogz.service.impl;


import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.zang.blogz.constant.RedisConstant;
import com.zang.blogz.entity.Role;
import com.zang.blogz.entity.UserRole;
import com.zang.blogz.mapper.UserRoleMapper;
import com.zang.blogz.service.RedisService;
import com.zang.blogz.service.RoleService;
import com.zang.blogz.service.UserRoleService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import io.github.vampireachao.stream.core.optional.Opp;
import io.github.vampireachao.stream.core.stream.Steam;
import io.github.vampireachao.stream.plugin.mybatisplus.Many;
import io.github.vampireachao.stream.plugin.mybatisplus.OneToMany;
import io.github.vampireachao.stream.plugin.mybatisplus.OneToManyToOne;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author 朵橙i
 * @since 2022-06-17
 */
@Service
public class UserRoleServiceImpl extends ServiceImpl<UserRoleMapper, UserRole> implements UserRoleService {

    @Autowired
    private RedisService redisService;

    @Override
    /**
     * 根据当前登录的用户判断其所拥有的角色
     */
    public List<String> getRoleByLoginAdmin(Integer userId) {

        Object o = redisService.get(userId + ":" + RedisConstant.USER_ROLE);

        if (Opp.of(o).isPresent()){

            return JSONUtil.toList(o.toString(), String.class);
        }else {

            QueryWrapper<UserRole> userRoleQueryWrapper = new QueryWrapper<>();

            userRoleQueryWrapper.lambda().eq(UserRole::getUserId, userId);

            Map<Integer, List<String>> query = OneToManyToOne.of(UserRole::getUserId)
                    .eq(userId)
                    .value(UserRole::getRoleId)
                    .attachKey(Role::getId)
                    .attachValue(Role::getRoleName)
                    .query();
            List<String> roleList = query.get(userId);

            redisService.set(userId + ":" + RedisConstant.USER_ROLE,JSONUtil.toJsonStr(roleList));

            return roleList;
        }
    }

    @Override
    public List<Integer> getRoleIdsByLoginAdmin(Integer userId) {

        LambdaQueryWrapper<UserRole> queryWrapper = new LambdaQueryWrapper<>();

        queryWrapper.eq(UserRole::getUserId,userId);

        return Steam.of(list(queryWrapper)).map(UserRole::getRoleId).toList();
    }

    @Override
    @Transactional
    public List<UserRole> updateResource(Integer loginId, List<Integer> roles) {

        LambdaUpdateWrapper<UserRole> updateWrapper = new LambdaUpdateWrapper<>();

        updateWrapper.eq(UserRole::getUserId, loginId);

        remove(updateWrapper);

        List<UserRole> userRoles = new ArrayList<>(roles.size());

        Steam.of(roles).forEach(role -> userRoles.add(UserRole.builder().userId(loginId).roleId(role).build()));

        saveBatch(userRoles);

        return userRoles;

    }

    @Override
    public Boolean isCanDelete(Integer roleId) {

        LambdaQueryWrapper<UserRole> queryWrapper = new LambdaQueryWrapper<>();

        queryWrapper.eq(UserRole::getRoleId, roleId);

        return Opp.ofColl(list(queryWrapper)).isEmpty();
    }


}
